﻿namespace Pub.Class
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Text;

    public static class DataTableExtensions
    {
        private const string tableTemplate = " <Worksheet ss:Name=\"{0}\">\r\n  <Table ss:ExpandedColumnCount=\"{1}\" ss:ExpandedRowCount=\"{2}\" x:FullColumns=\"1\"\r\n   x:FullRows=\"1\" ss:DefaultColumnWidth=\"54\" ss:DefaultRowHeight=\"13.5\">\r\n{3}\r\n  </Table>\r\n  <WorksheetOptions xmlns=\"urn:schemas-microsoft-com:office:excel\">\r\n   <PageSetup>\r\n    <Header x:Margin=\"0.3\"/>\r\n    <Footer x:Margin=\"0.3\"/>\r\n    <PageMargins x:Bottom=\"0.75\" x:Left=\"0.7\" x:Right=\"0.7\" x:Top=\"0.75\"/>\r\n   </PageSetup>\r\n   <Print>\r\n    <ValidPrinterInfo/>\r\n    <PaperSizeIndex>0</PaperSizeIndex>\r\n    <VerticalResolution>0</VerticalResolution>\r\n    <NumberofCopies>0</NumberofCopies>\r\n   </Print>\r\n   <Selected/>\r\n   <Panes>\r\n    <Pane>\r\n     <Number>3</Number>\r\n     <ActiveRow>1</ActiveRow>\r\n    </Pane>\r\n   </Panes>\r\n   <ProtectObjects>False</ProtectObjects>\r\n   <ProtectScenarios>False</ProtectScenarios>\r\n  </WorksheetOptions>\r\n </Worksheet>";
        private const string xlsTemplate = "<?xml version=\"1.0\"?>\r\n<?mso-application progid=\"Excel.Sheet\"?>\r\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n xmlns:o=\"urn:schemas-microsoft-com:office:office\"\r\n xmlns:x=\"urn:schemas-microsoft-com:office:excel\"\r\n xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n xmlns:html=\"http://www.w3.org/TR/REC-html40\">\r\n <DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">\r\n  <Created>{0}T00:00:00Z</Created>\r\n  <LastSaved>{0}T00:00:00Z</LastSaved>\r\n  <Version>14.00</Version>\r\n </DocumentProperties>\r\n <OfficeDocumentSettings xmlns=\"urn:schemas-microsoft-com:office:office\">\r\n  <AllowPNG/>\r\n  <RemovePersonalInformation/>\r\n </OfficeDocumentSettings>\r\n <ExcelWorkbook xmlns=\"urn:schemas-microsoft-com:office:excel\">\r\n  <WindowHeight>8010</WindowHeight>\r\n  <WindowWidth>14805</WindowWidth>\r\n  <WindowTopX>240</WindowTopX>\r\n  <WindowTopY>105</WindowTopY>\r\n  <ProtectStructure>False</ProtectStructure>\r\n  <ProtectWindows>False</ProtectWindows>\r\n </ExcelWorkbook>\r\n <Styles>\r\n  <Style ss:ID=\"Default\" ss:Name=\"Normal\">\r\n   <Alignment ss:Vertical=\"Bottom\"/>\r\n   <Borders/>\r\n   <Font ss:FontName=\"宋体\" x:CharSet=\"134\" ss:Size=\"11\" ss:Color=\"#000000\"/>\r\n   <Interior/>\r\n   <NumberFormat/>\r\n   <Protection/>\r\n  </Style>\r\n  <Style ss:ID=\"s62\">\r\n   <Font ss:FontName=\"宋体\" x:CharSet=\"134\" ss:Size=\"11\" ss:Color=\"#000000\"\r\n    ss:Bold=\"1\"/>\r\n  </Style>\r\n </Styles>\r\n{1}\r\n</Workbook>";

        public static object Cell(this DataTable dt, int row, int column)
        {
            return dt.Rows[row][column];
        }

        public static DataTable ChangeColumnName(this DataTable source, Dictionary<string, string> list)
        {
            return source.ChangeColumnName(list);
        }

        public static DataTable ChangeColumnName(this DataTable source, Dictionary<string, string> list, bool isFilter = false)
        {
            Action<string> action = null;
            DataTable output = new DataTable();
            if (isFilter)
            {
                if (action == null)
                {
                    action = delegate (string p) {
                        output.Columns.Add(list[p]);
                    };
                }
                list.Keys.Do<string>(action);
                foreach (DataRow row in source.Rows)
                {
                    DataRow row2 = output.NewRow();
                    foreach (string str in list.Keys)
                    {
                        row2[list[str]] = row[str];
                    }
                    output.Rows.Add(row2);
                }
            }
            else
            {
                foreach (DataColumn column in source.Columns)
                {
                    string columnName = column.ColumnName;
                    if (list.ContainsKey(columnName))
                    {
                        columnName = list[columnName];
                    }
                    output.Columns.Add(columnName);
                }
                foreach (DataRow row3 in source.Rows)
                {
                    DataRow row4 = output.NewRow();
                    foreach (DataColumn column2 in source.Columns)
                    {
                        string key = column2.ColumnName;
                        if (list.ContainsKey(key))
                        {
                            key = list[key];
                        }
                        row4[key] = row3[column2.ColumnName];
                    }
                    output.Rows.Add(row4);
                }
            }
            return output;
        }

        public static T Get<T>(this DataRow row, string field)
        {
            return row.Get<T>(field, default(T));
        }

        public static T Get<T>(this DataRowView row, string field)
        {
            return row.Get<T>(field, default(T));
        }

        public static T Get<T>(this DataRow row, string field, T defaultValue)
        {
            object obj2 = row[field];
            if (obj2 == DBNull.Value)
            {
                return defaultValue;
            }
            return obj2.ConvertTo<T>(defaultValue);
        }

        public static T Get<T>(this DataRowView row, string field, T defaultValue)
        {
            object obj2 = row[field];
            if (obj2 == DBNull.Value)
            {
                return defaultValue;
            }
            return obj2.ConvertTo<T>(defaultValue);
        }

        public static List<TResult> OrderBy<TResult>(this DataTable dt, string orderBy) where TResult: class, new()
        {
            return dt.OrderBy(orderBy).ToList<TResult>();
        }

        public static DataTable OrderBy(this DataTable dt, string orderBy)
        {
            dt.DefaultView.Sort = orderBy;
            return dt.DefaultView.ToTable();
        }

        public static DataTable SwapDTCR(this DataTable inputDT)
        {
            DataTable table = new DataTable();
            table.Columns.Add(inputDT.Columns[0].ColumnName);
            foreach (DataRow row in inputDT.Rows)
            {
                string columnName = row[0].ToString();
                table.Columns.Add(columnName);
            }
            for (int i = 1; i <= (inputDT.Columns.Count - 1); i++)
            {
                DataRow row2 = table.NewRow();
                row2[0] = inputDT.Columns[i].ColumnName;
                for (int j = 0; j <= (inputDT.Rows.Count - 1); j++)
                {
                    string str2 = inputDT.Rows[j][i].ToString();
                    row2[j + 1] = str2;
                }
                table.Rows.Add(row2);
            }
            return table;
        }

        public static string ToCSV(this DataSet dataSet)
        {
            StringBuilder builder = new StringBuilder();
            foreach (DataTable table in dataSet.Tables)
            {
                builder.Append(table.ToCSV());
            }
            return builder.ToString();
        }

        public static string ToCSV(this DataTable dataTable)
        {
            return dataTable.ToCSV(',');
        }

        public static void ToCSV(this DataSet ds, string fileName)
        {
            FileDirectory.FileDelete(fileName);
            Log.Write(fileName, ds.ToCSV());
        }

        public static string ToCSV(this DataTable dataTable, char c = ',')
        {
            if (dataTable.IsNull())
            {
                return string.Empty;
            }
            StringBuilder sb = new StringBuilder();
            foreach (DataColumn column in dataTable.Columns)
            {
                sb.AppendFormat("{0}{1}", column.ColumnName.ToString(), c);
            }
            sb.RemoveLastChar(c.ToString());
            sb.Append("\n");
            foreach (DataRowView view in dataTable.DefaultView)
            {
                foreach (DataColumn column2 in dataTable.Columns)
                {
                    sb.AppendFormat("{0}{1}", view[column2.ColumnName].ToString(), c);
                }
                sb.RemoveLastChar(c.ToString());
                sb.Append("\n");
            }
            return sb.ToString();
        }

        public static void ToCSV(this DataTable dt, string fileName)
        {
            FileDirectory.FileDelete(fileName);
            Log.Write(fileName, dt.ToCSV(','));
        }

        public static string ToDataTableJson(this DataTable dt)
        {
            if (dt.IsNull())
            {
                return "[]";
            }
            StringBuilder builder = new StringBuilder();
            builder.Append("[");
            foreach (DataRow row in dt.Rows)
            {
                builder.Append("{");
                foreach (DataColumn column in dt.Columns)
                {
                    builder.AppendFormat("\"{0}\":{1},", column.ColumnName, row[column].ToJson());
                }
                builder.Remove(builder.Length - 1, 1);
                builder.Append("},");
            }
            dt.Dispose();
            dt = null;
            if (builder.Length > 1)
            {
                builder.Remove(builder.Length - 1, 1);
            }
            builder.Append("]");
            return builder.ToString();
        }

        public static TResult ToEntity<TResult>(this DataTable dt) where TResult: class, new()
        {
            return dt.ToList<TResult>().FirstOrDefault<TResult>();
        }

        private static string toExcel(this DataTable dt, int i = 1)
        {
            StringBuilder builder = new StringBuilder();
            int count = dt.Columns.Count;
            int num2 = dt.Rows.Count;
            if (count == 0)
            {
                return string.Empty;
            }
            string str = (dt.TableName.IsNullEmpty() ? ("Sheet" + i) : dt.TableName).TrimEnd(new char[] { '$' });
            builder.AppendLine("   <Row>");
            for (int j = 0; j < count; j++)
            {
                builder.AppendLine("    <Cell ss:StyleID=\"s62\"><Data ss:Type=\"String\">{0}</Data></Cell>".FormatWith(dt.Columns[i].ColumnName));
            }
            builder.AppendLine("   </Row>");
            if (num2 > 0)
            {
                for (int k = 0; k < num2; k++)
                {
                    builder.AppendLine("   <Row>");
                    for (int m = 0; m < count; m++)
                    {
                        builder.AppendLine("    <Cell><Data ss:Type=\"String\">{0}</Data></Cell>".FormatWith(dt.Rows[k][m].ToString()));
                    }
                    builder.AppendLine("   </Row>");
                }
            }
            return " <Worksheet ss:Name=\"{0}\">\r\n  <Table ss:ExpandedColumnCount=\"{1}\" ss:ExpandedRowCount=\"{2}\" x:FullColumns=\"1\"\r\n   x:FullRows=\"1\" ss:DefaultColumnWidth=\"54\" ss:DefaultRowHeight=\"13.5\">\r\n{3}\r\n  </Table>\r\n  <WorksheetOptions xmlns=\"urn:schemas-microsoft-com:office:excel\">\r\n   <PageSetup>\r\n    <Header x:Margin=\"0.3\"/>\r\n    <Footer x:Margin=\"0.3\"/>\r\n    <PageMargins x:Bottom=\"0.75\" x:Left=\"0.7\" x:Right=\"0.7\" x:Top=\"0.75\"/>\r\n   </PageSetup>\r\n   <Print>\r\n    <ValidPrinterInfo/>\r\n    <PaperSizeIndex>0</PaperSizeIndex>\r\n    <VerticalResolution>0</VerticalResolution>\r\n    <NumberofCopies>0</NumberofCopies>\r\n   </Print>\r\n   <Selected/>\r\n   <Panes>\r\n    <Pane>\r\n     <Number>3</Number>\r\n     <ActiveRow>1</ActiveRow>\r\n    </Pane>\r\n   </Panes>\r\n   <ProtectObjects>False</ProtectObjects>\r\n   <ProtectScenarios>False</ProtectScenarios>\r\n  </WorksheetOptions>\r\n </Worksheet>".FormatWith(new object[] { str, count, (num2 + 1), builder.ToString() });
        }

        public static void ToExcel(this DataSet source, string fileName)
        {
            StringBuilder sbXML = new StringBuilder();
            source.Tables.Do((Action<object, int>) ((p, i) => sbXML.Append(((DataTable) p).toExcel(i))));
            FileDirectory.FileDelete(fileName);
            Log.Write(fileName, "<?xml version=\"1.0\"?>\r\n<?mso-application progid=\"Excel.Sheet\"?>\r\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n xmlns:o=\"urn:schemas-microsoft-com:office:office\"\r\n xmlns:x=\"urn:schemas-microsoft-com:office:excel\"\r\n xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n xmlns:html=\"http://www.w3.org/TR/REC-html40\">\r\n <DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">\r\n  <Created>{0}T00:00:00Z</Created>\r\n  <LastSaved>{0}T00:00:00Z</LastSaved>\r\n  <Version>14.00</Version>\r\n </DocumentProperties>\r\n <OfficeDocumentSettings xmlns=\"urn:schemas-microsoft-com:office:office\">\r\n  <AllowPNG/>\r\n  <RemovePersonalInformation/>\r\n </OfficeDocumentSettings>\r\n <ExcelWorkbook xmlns=\"urn:schemas-microsoft-com:office:excel\">\r\n  <WindowHeight>8010</WindowHeight>\r\n  <WindowWidth>14805</WindowWidth>\r\n  <WindowTopX>240</WindowTopX>\r\n  <WindowTopY>105</WindowTopY>\r\n  <ProtectStructure>False</ProtectStructure>\r\n  <ProtectWindows>False</ProtectWindows>\r\n </ExcelWorkbook>\r\n <Styles>\r\n  <Style ss:ID=\"Default\" ss:Name=\"Normal\">\r\n   <Alignment ss:Vertical=\"Bottom\"/>\r\n   <Borders/>\r\n   <Font ss:FontName=\"宋体\" x:CharSet=\"134\" ss:Size=\"11\" ss:Color=\"#000000\"/>\r\n   <Interior/>\r\n   <NumberFormat/>\r\n   <Protection/>\r\n  </Style>\r\n  <Style ss:ID=\"s62\">\r\n   <Font ss:FontName=\"宋体\" x:CharSet=\"134\" ss:Size=\"11\" ss:Color=\"#000000\"\r\n    ss:Bold=\"1\"/>\r\n  </Style>\r\n </Styles>\r\n{1}\r\n</Workbook>".FormatWith(DateTime.Now.ToString("yyyy-MM-dd"), sbXML.ToString()));
            source.Dispose();
            source = null;
        }

        public static void ToExcel(this DataTable dt, string fileName)
        {
            FileDirectory.FileDelete(fileName);
            Log.Write(fileName, "<?xml version=\"1.0\"?>\r\n<?mso-application progid=\"Excel.Sheet\"?>\r\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n xmlns:o=\"urn:schemas-microsoft-com:office:office\"\r\n xmlns:x=\"urn:schemas-microsoft-com:office:excel\"\r\n xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n xmlns:html=\"http://www.w3.org/TR/REC-html40\">\r\n <DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">\r\n  <Created>{0}T00:00:00Z</Created>\r\n  <LastSaved>{0}T00:00:00Z</LastSaved>\r\n  <Version>14.00</Version>\r\n </DocumentProperties>\r\n <OfficeDocumentSettings xmlns=\"urn:schemas-microsoft-com:office:office\">\r\n  <AllowPNG/>\r\n  <RemovePersonalInformation/>\r\n </OfficeDocumentSettings>\r\n <ExcelWorkbook xmlns=\"urn:schemas-microsoft-com:office:excel\">\r\n  <WindowHeight>8010</WindowHeight>\r\n  <WindowWidth>14805</WindowWidth>\r\n  <WindowTopX>240</WindowTopX>\r\n  <WindowTopY>105</WindowTopY>\r\n  <ProtectStructure>False</ProtectStructure>\r\n  <ProtectWindows>False</ProtectWindows>\r\n </ExcelWorkbook>\r\n <Styles>\r\n  <Style ss:ID=\"Default\" ss:Name=\"Normal\">\r\n   <Alignment ss:Vertical=\"Bottom\"/>\r\n   <Borders/>\r\n   <Font ss:FontName=\"宋体\" x:CharSet=\"134\" ss:Size=\"11\" ss:Color=\"#000000\"/>\r\n   <Interior/>\r\n   <NumberFormat/>\r\n   <Protection/>\r\n  </Style>\r\n  <Style ss:ID=\"s62\">\r\n   <Font ss:FontName=\"宋体\" x:CharSet=\"134\" ss:Size=\"11\" ss:Color=\"#000000\"\r\n    ss:Bold=\"1\"/>\r\n  </Style>\r\n </Styles>\r\n{1}\r\n</Workbook>".FormatWith(DateTime.Now.ToString("yyyy-MM-dd"), dt.toExcel(1)));
        }

        public static string ToJson(this DataSet ds)
        {
            StringBuilder builder = new StringBuilder();
            if (ds.IsNull() || (ds.Tables.Count == 0))
            {
                return "[]";
            }
            builder.Append("[");
            foreach (DataTable table in ds.Tables)
            {
                builder.Append(table.ToJson());
                builder.Append(",");
            }
            builder.Remove(builder.Length - 1, 1);
            builder.Append("]");
            return builder.ToString();
        }

        public static string ToJson(this DataTable dt)
        {
            return dt.ToDataTableJson();
        }

        public static string ToJson(this DataTable dt, params string[] fields)
        {
            return dt.ToJson(fields, null);
        }

        public static string ToJson(this DataTable dt, int[] fields, string[] alias)
        {
            if (dt.IsNull())
            {
                return "[]";
            }
            if (alias.IsNull() || (fields.Length != alias.Length))
            {
                Msg.WriteEnd("参数错误！");
            }
            if (fields.IsNull() || (fields.Length == 0))
            {
                return dt.ToDataTableJson();
            }
            StringBuilder builder = new StringBuilder();
            builder.Append("[");
            foreach (DataRow row in dt.Rows)
            {
                builder.Append("{");
                int index = 0;
                foreach (int num2 in fields)
                {
                    builder.AppendFormat("\"{0}\":{1},", alias[index], row[num2].ToJson());
                    index++;
                }
                builder.Remove(builder.Length - 1, 1);
                builder.Append("},");
            }
            dt.Dispose();
            dt = null;
            if (builder.Length > 1)
            {
                builder.Remove(builder.Length - 1, 1);
            }
            builder.Append("]");
            return builder.ToString();
        }

        public static string ToJson(this DataTable dt, string[] fields, string[] alias)
        {
            if (dt.IsNull())
            {
                return "[]";
            }
            if (alias.IsNull() || (fields.Length != alias.Length))
            {
                alias = fields;
            }
            if (fields.IsNull() || (fields.Length == 0))
            {
                return dt.ToDataTableJson();
            }
            StringBuilder builder = new StringBuilder();
            builder.Append("[");
            foreach (DataRow row in dt.Rows)
            {
                builder.Append("{");
                int index = 0;
                foreach (string str in fields)
                {
                    builder.AppendFormat("\"{0}\":{1},", alias[index], row[str].ToJson());
                    index++;
                }
                builder.Remove(builder.Length - 1, 1);
                builder.Append("},");
            }
            dt.Dispose();
            dt = null;
            if (builder.Length > 1)
            {
                builder.Remove(builder.Length - 1, 1);
            }
            builder.Append("]");
            return builder.ToString();
        }

        public static List<TResult> ToList<TResult>(this DataTable dt) where TResult: class, new()
        {
            List<TResult> list = new List<TResult>();
            if (!dt.IsNull() && (dt.Rows.Count != 0))
            {
                DataTableEntityBuilder<TResult> builder = DataTableEntityBuilder<TResult>.CreateBuilder(dt.Rows[0]);
                foreach (DataRow row in dt.Rows)
                {
                    list.Add(builder.Build(row));
                }
                dt.Dispose();
                dt = null;
            }
            return list;
        }

        public static List<TResult> ToList2<TResult>(this DataTable dt) where TResult: class, new()
        {
            List<PropertyInfo> prlist = new List<PropertyInfo>();
            Type type = typeof(TResult);
            Array.ForEach<PropertyInfo>(type.GetPropertiesCache(), delegate (PropertyInfo p) {
                if (dt.Columns.IndexOf(p.Name) != -1)
                {
                    prlist.Add(p);
                }
            });
            List<TResult> list = new List<TResult>();
            IEnumerator enumerator = dt.Rows.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    DataRow row = (DataRow) enumerator.Current;
                    TResult ob = Activator.CreateInstance<TResult>();
                    prlist.ForEach(delegate (PropertyInfo p) {
                        if (row[p.Name] != DBNull.Value)
                        {
                            p.SetValue(ob, row[p.Name], null);
                        }
                    });
                    list.Add(ob);
                }
            return list;
        }

        public static List<TResult> ToList3<TResult>(this DataTable dt) where TResult: class, new()
        {
            List<TResult> list = new List<TResult>();
            if (!dt.IsNull())
            {
                int count = dt.Rows.Count;
                for (int i = 0; i < count; i++)
                {
                    TResult local = Activator.CreateInstance<TResult>();
                    foreach (DataColumn column in dt.Rows[0].Table.Columns)
                    {
                        if (!dt.Rows[i][column.ColumnName].IsNull() && !string.IsNullOrEmpty(dt.Rows[i][column.ColumnName].ToString()))
                        {
                            local.GetType().GetPropertyCache(column.ColumnName).SetValue(local, dt.Rows[i][column.ColumnName], null);
                        }
                    }
                    list.Add(local);
                }
                dt.Dispose();
                dt = null;
            }
            return list;
        }

        public static List<TResult> ToPage<TResult>(this DataTable dt, int pageIndex, int pageSize, out int totalRecords) where TResult: class, new()
        {
            totalRecords = dt.Rows.Count;
            int num = (pageIndex - 1) * pageSize;
            int num2 = num + pageSize;
            if ((num > totalRecords) || (num < 0))
            {
                num = 0;
                num2 = pageSize;
            }
            if (num2 > (totalRecords + pageSize))
            {
                num = totalRecords - pageSize;
                num2 = totalRecords;
            }
            DataTable table = dt.Clone();
            for (int i = num; i < num2; i++)
            {
                if (i >= totalRecords)
                {
                    break;
                }
                table.Rows.Add(dt.Rows[i].ItemArray);
            }
            return table.ToList<TResult>();
        }

        public static DataTable ToPage(this DataTable dt, int pageIndex, int pageSize, out int totalRecords)
        {
            totalRecords = dt.Rows.Count;
            int num = (pageIndex - 1) * pageSize;
            int num2 = num + pageSize;
            if ((num > totalRecords) || (num < 0))
            {
                num = 0;
                num2 = pageSize;
            }
            if (num2 > (totalRecords + pageSize))
            {
                num = totalRecords - pageSize;
                num2 = totalRecords;
            }
            DataTable table = dt.Clone();
            for (int i = num; i < num2; i++)
            {
                if (i >= totalRecords)
                {
                    return table;
                }
                table.Rows.Add(dt.Rows[i].ItemArray);
            }
            return table;
        }

        public static List<TResult> Where<TResult>(this DataTable dt, string where) where TResult: class, new()
        {
            return dt.Where(where).ToList<TResult>();
        }

        public static DataTable Where(this DataTable dt, string where)
        {
            DataTable table = dt.Clone();
            foreach (DataRow row in dt.Select(where))
            {
                table.Rows.Add(row.ItemArray);
            }
            return table;
        }
    }
}

